﻿#include "Input.h"
#include "InputEventHandle.h"
#include <list>
#include <queue>

namespace DYEngine
{
	struct IntData
	{
		int x;
		int y;
		IntData(int pX, int pY): x(pX), y(pY) { }
	};

	struct FloatData
	{
		float x;
		float y;
		FloatData(float pX, float pY): x(pX), y(pY) { }
	};

	static std::list<InputEventHandle*> sHandleList;
	static std::queue<IntData> sScreenChangeQueue;
	static std::queue<FloatData> sCursorMoveQueue;
	static std::queue<IntData> sKeyQueue;
	static std::queue<IntData> sMouseButtonQueue;
	static std::queue<FloatData> sScrollQueue;

	void Input::AddEvent(InputEventHandle* pHandle)
	{
		if (pHandle == nullptr) return;
		sHandleList.push_back(pHandle);
	}

	void Input::RemoveEvent(InputEventHandle* pHandle)
	{
		if (pHandle == nullptr) return;
		sHandleList.remove(pHandle);
	}

	void Input::ScreenSizeChange(int w, int h)
	{
		sScreenChangeQueue.push(IntData(w, h));
	}

	void Input::CursorMove(float x, float y)
	{
		sCursorMoveQueue.push(FloatData(x, y));
	}

	void Input::KeyPress(int key, int action)
	{
		sKeyQueue.push(IntData(key, action));
	}

	void Input::MouseButtonPress(int key, int action)
	{
		sMouseButtonQueue.push(IntData(key, action));
	}

	void Input::ScrollEvent(float xoffset, float yoffset)
	{
		sScrollQueue.push(FloatData(xoffset, yoffset));
	}

	void Input::Emit()
	{
		for (auto iter = sHandleList.begin(); iter != sHandleList.end(); iter++)
		{
			InputEventHandle* handle = (*iter);
			
			while (!sScreenChangeQueue.empty())
			{
				IntData data = sScreenChangeQueue.front();
				handle->ScreenSizeChange(data.x, data.y);
				sScreenChangeQueue.pop();
			}

			// 先发送按键事件，再发送移动事件
			while (!sKeyQueue.empty())
			{
				IntData data = sKeyQueue.front();
				handle->KeyPress(data.x, data.y);
				sKeyQueue.pop();
			}

			while (!sMouseButtonQueue.empty())
			{
				IntData data = sMouseButtonQueue.front();
				handle->MouseButtonPress(data.x, data.y);
				sMouseButtonQueue.pop();
			}

			while (!sScrollQueue.empty())
			{
				FloatData data = sScrollQueue.front();
				handle->ScrollEvent(data.x, data.y);
				sScrollQueue.pop();
			}

			while (!sCursorMoveQueue.empty())
			{
				FloatData data = sCursorMoveQueue.front();
				handle->CursorMove(data.x, data.y);
				sCursorMoveQueue.pop();
			}
		}
	}

	void Input::GetCursorPos(float& x, float& y)
	{
		Device::GetMousePos(x, y);
	}
}